﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Transactions;
using SMA.GENTEv1.Dados;

namespace SMA.GENTEv1
{
    public class FrotaRegraContrato
    {
        #region Variaveis Membro
        private int _idFrotaRegraContrato;
        private Contrato _contrato;
        private double _limiteKMCarro;
        private int _qntMinimaCarro;
        private List<FrotaModelo> _modelo;
        private Cidade _localidade;
        private FrotaLimiteAnoFabricacao _limiteAnoFabricacao;
        private DataTable _gradeRegraContrato;
        private DataTable _comboContrato;
        private DataTable _comboLocalidade;
        private GENTEEntities _context;
        #endregion

        #region Parametros
        public int IdFrotaRegraContrato
        {
            get { return _idFrotaRegraContrato; }
            set { _idFrotaRegraContrato = value; }
        }

        public Contrato Contrato
        {
            get { return _contrato; }
            set { _contrato = value; }
        }

        public double LimiteKMCarro
        {
            get { return _limiteKMCarro; }
            set { _limiteKMCarro = value; }
        }

        public int QntMinimaCarro
        {
            get { return _qntMinimaCarro; }
            set { _qntMinimaCarro = value; }
        }

        public List<FrotaModelo> Modelo
        {
            get { return _modelo; }
            set { _modelo = value; }
        }

        public Cidade Localidade
        {
            get { return _localidade; }
            set { _localidade = value; }
        }

        public FrotaLimiteAnoFabricacao LimiteAnoFabricacao
        {
            get { return _limiteAnoFabricacao; }
            set { _limiteAnoFabricacao = value; }
        }
        #endregion

        #region Construtores
        public FrotaRegraContrato()
        {
            _context = new GENTEEntities();
        }

        public FrotaRegraContrato(int _idregracontrato, bool _carregaDados, bool _carregaContrato, bool _carregaLocalidade, 
                                  bool _carregaAnoFabricacao, bool _carregaVeiculos)
        {
            _context = new GENTEEntities();
            if (!_carregaDados)
                this._idFrotaRegraContrato = _idregracontrato;
            else
                Carregar(_idregracontrato, _carregaContrato, _carregaLocalidade, _carregaAnoFabricacao, _carregaVeiculos);
        }
        #endregion

        #region Métodos Privados
        private void Carregar(int _idregracontrato, bool _carregaContrato, bool _carregaLocalidade, 
                              bool _carregaAnoFabricacao, bool _carregaVeiculos)
        {
            try
            {
                var consulta = (from regracontrato in _context.tab_frota_regra_contrato
                                where regracontrato.id_frota_regra_contrato == _idregracontrato
                                select new
                                {
                                    regracontrato.id_frota_regra_contrato,
                                    regracontrato.tab_contrato.Id_contrato,
                                    regracontrato.tab_cidade.id_cidade,
                                    regracontrato.limite_km_por_carro,
                                    regracontrato.tab_frota_limite_ano_fabricacao.id_limite_ano_fabricacao,
                                    regracontrato.qnt_minima_carro
                                });

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    this._idFrotaRegraContrato = list.id_frota_regra_contrato;

                    if (_carregaContrato)
                        this._contrato = new Contrato(list.Id_contrato);
                    else
                    {
                        this._contrato = new Contrato();
                        this._contrato.IdContrato = list.Id_contrato;
                    }

                    if (_carregaLocalidade)
                        this._localidade = new Cidade(list.id_cidade);
                    else
                    {
                        this._localidade = new Cidade();
                        this._localidade.IdCidade = list.id_cidade;
                    }

                    this._limiteKMCarro = list.limite_km_por_carro;
                    this._limiteAnoFabricacao = new FrotaLimiteAnoFabricacao(list.id_limite_ano_fabricacao, _carregaAnoFabricacao);
                    this._qntMinimaCarro = list.qnt_minima_carro;

                    if (_carregaVeiculos)
                    {
                        FrotaModelo modelo = new FrotaModelo();
                        this._modelo = modelo.SelectModelosRegraContrato(list.id_frota_regra_contrato);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void GradeControleFrota()
        {
            try
            {
                DataColumn idfrotaregracontrole = new DataColumn();
                idfrotaregracontrole.ColumnName = "IdFrotaRegraContrato";
                idfrotaregracontrole.DataType = Type.GetType("System.Int32");
                _gradeRegraContrato.Columns.Add(idfrotaregracontrole);

                DataColumn nomecontrato = new DataColumn();
                nomecontrato.ColumnName = "NomeContrato";
                nomecontrato.DataType = Type.GetType("System.String");
                nomecontrato.Caption = "Contrato";
                _gradeRegraContrato.Columns.Add(nomecontrato);

                DataColumn localidade = new DataColumn();
                localidade.ColumnName = "Localidade";
                localidade.DataType = Type.GetType("System.String");
                localidade.Caption = "Localidade";
                _gradeRegraContrato.Columns.Add(localidade);

                DataColumn qtdemin = new DataColumn();
                qtdemin.ColumnName = "QtdeMin";
                qtdemin.DataType = Type.GetType("System.Int32");
                qtdemin.Caption = "Quantidade mínima";
                _gradeRegraContrato.Columns.Add(qtdemin);

                DataColumn limitekm = new DataColumn();
                limitekm.ColumnName = "LimiteKM";
                limitekm.DataType = Type.GetType("System.Int32");
                limitekm.Caption = "Limite KM";
                _gradeRegraContrato.Columns.Add(limitekm);

                DataColumn anofab = new DataColumn();
                anofab.ColumnName = "AnoFab";
                anofab.DataType = Type.GetType("System.String");
                anofab.Caption = "Limite Ano Fab";
                _gradeRegraContrato.Columns.Add(anofab);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private int RetornaIdRegraContrato()
        {
            try
            {
                int idregracontrato = 0;

                var consulta = (from regracontrato in _context.tab_frota_regra_contrato
                                orderby regracontrato.id_frota_regra_contrato descending
                                select new
                                {
                                    regracontrato.id_frota_regra_contrato
                                }).Take(1);
                                

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    idregracontrato = list.id_frota_regra_contrato;
                }

                return idregracontrato;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void SalvarVeiculosFrota()
        {
            try
            {
                for (int i = 0; i < this._modelo.Count; i++)
                {
                    tab_frota_regra_contrato_frota_modelo tabRegraContratoModelo = new tab_frota_regra_contrato_frota_modelo();
                    tabRegraContratoModelo.tab_frota_regra_contratoReference.EntityKey = new EntityKey("GENTEEntities.tab_frota_regra_contrato", "id_frota_regra_contrato", this._idFrotaRegraContrato);
                    tabRegraContratoModelo.tab_frota_modeloReference.EntityKey = new EntityKey("GENTEEntities.tab_frota_modelo", "id_frota_modelo", this._modelo[i].IdFrotaModelo);

                    _context.AddTotab_frota_regra_contrato_frota_modelo(tabRegraContratoModelo);
                    _context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void ExcluirVeiculosFrota()
        {
            try
            {
                var consulta = (from regracontratomodelo in _context.tab_frota_regra_contrato_frota_modelo
                                where regracontratomodelo.tab_frota_regra_contrato.id_frota_regra_contrato == this._idFrotaRegraContrato
                                select regracontratomodelo);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    _context.DeleteObject(list);
                    _context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private bool VerificaCadastro()
        {
            try
            {
                bool verifica = false;

                if (this._contrato == null)
                    throw new Exception("É necessário informar o contrato!");

                if (this._contrato.IdContrato == 0)
                    throw new Exception("É necessário informar o contrato!");

                if (this._localidade == null)
                    throw new Exception("É necessário informar a localidade!");

                if (this._localidade.IdCidade == 0)
                    throw new Exception("É necessário informar a localidade!");

                if (this._limiteKMCarro == 0)
                    throw new Exception("É necessário informar o limite de quilometragem!");

                if (this._limiteAnoFabricacao == null)
                    throw new Exception("É necessário informar o limite de ano de fabricação!");

                if (this._limiteAnoFabricacao.IdLimiteAnoFabricacao == 0)
                    throw new Exception("É necessário informar o limite de ano de fabricação!");

                if (this._qntMinimaCarro == 0)
                    throw new Exception("É necessário informar a quantidade mínima de carro!");

                if (this._modelo == null)
                    throw new Exception("É necessário informar os veículos para parametrização!");

                if (this._modelo.Count == 0)
                    throw new Exception("É necessário informar os veículos para parametrização!");

                if (this._idFrotaRegraContrato == 0)
                {
                    var consulta = (from regracontrato in _context.tab_frota_regra_contrato
                                    where regracontrato.tab_contrato.Id_contrato == this._contrato.IdContrato
                                    && regracontrato.tab_cidade.id_cidade == this._localidade.IdCidade
                                    select new
                                    {
                                        regracontrato.id_frota_regra_contrato
                                    });

                    if (consulta.ToList().Count > 0)
                        throw new Exception("Foi encontrado uma parametrização de controle de frotas para o contrato e localidade informados. Operação cancelada!");
                }

                verifica = true;
                return verifica;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void EstruturaComboContrato()
        {
            DataColumn idcontrato = new DataColumn();
            idcontrato.ColumnName = "IdContrato";
            idcontrato.DataType = Type.GetType("System.Int32");
            _comboContrato.Columns.Add(idcontrato);

            DataColumn descricao = new DataColumn();
            descricao.ColumnName = "Descricao";
            descricao.DataType = Type.GetType("System.String");
            _comboContrato.Columns.Add(descricao);
        }

        private void EstruturaComboLocalidade()
        {
            DataColumn idcidade = new DataColumn();
            idcidade.ColumnName = "IdCidade";
            idcidade.DataType = Type.GetType("System.Int32");
            _comboLocalidade.Columns.Add(idcidade);

            DataColumn nomecidade = new DataColumn();
            nomecidade.ColumnName = "NomeCidade";
            nomecidade.DataType = Type.GetType("System.String");
            _comboLocalidade.Columns.Add(nomecidade);
        }
        #endregion

        #region Métodos Públicos

        #region Métodos de Seleção
        public List<FrotaRegraContrato> SelectPor(int _idmodelo)
        {
            try
            {
                List<FrotaRegraContrato> listRegraContrato = new List<FrotaRegraContrato>();

                var consulta = (from regracontratomodelo in _context.tab_frota_regra_contrato_frota_modelo
                                where regracontratomodelo.tab_frota_modelo.id_frota_modelo == _idmodelo
                                select new
                                {
                                    regracontratomodelo.tab_frota_regra_contrato.id_frota_regra_contrato,
                                    regracontratomodelo.tab_frota_regra_contrato.limite_km_por_carro,
                                    regracontratomodelo.tab_frota_regra_contrato.qnt_minima_carro
                                });

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    FrotaRegraContrato regracontrato = new FrotaRegraContrato();
                    regracontrato.IdFrotaRegraContrato = list.id_frota_regra_contrato;
                    regracontrato.LimiteKMCarro = list.limite_km_por_carro;
                    regracontrato.QntMinimaCarro = list.qnt_minima_carro;

                    listRegraContrato.Add(regracontrato);
                }

                return listRegraContrato;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public DataTable ExibirControleFrota(int _idcontrato, int _idlocalidade)
        {
            try
            {
                _gradeRegraContrato = new DataTable();

                GradeControleFrota();

                var consulta = (from regracontrato in _context.tab_frota_regra_contrato
                                where ((_idcontrato != 0) ? regracontrato.tab_contrato.Id_contrato == _idcontrato : (1 == 1))
                                && ((_idlocalidade != 0) ? regracontrato.tab_cidade.id_cidade == _idlocalidade : (2 == 2))
                                select new
                                {
                                    regracontrato.id_frota_regra_contrato,
                                    regracontrato.tab_contrato.Id_contrato,
                                    regracontrato.tab_cidade.id_cidade,
                                    regracontrato.limite_km_por_carro,
                                    regracontrato.tab_frota_limite_ano_fabricacao.id_limite_ano_fabricacao,
                                    regracontrato.qnt_minima_carro
                                });

                var listConsulta = consulta.ToList();

                DataRow registro;
                foreach (var list in listConsulta)
                {
                    FrotaRegraContrato regracontrato = new FrotaRegraContrato();
                    regracontrato.IdFrotaRegraContrato = list.id_frota_regra_contrato;
                    regracontrato.Contrato = new Contrato(list.Id_contrato);
                    regracontrato.Localidade = new Cidade(list.id_cidade);
                    regracontrato.LimiteKMCarro = list.limite_km_por_carro;
                    regracontrato.LimiteAnoFabricacao = new FrotaLimiteAnoFabricacao(list.id_limite_ano_fabricacao, true);
                    regracontrato.QntMinimaCarro = list.qnt_minima_carro;

                    registro = _gradeRegraContrato.NewRow();

                    registro["IdFrotaRegraContrato"] = regracontrato.IdFrotaRegraContrato;
                    registro["NomeContrato"] = regracontrato.Contrato.Descricao;
                    registro["Localidade"] = regracontrato.Localidade.NomeCidade;
                    registro["QtdeMin"] = regracontrato.QntMinimaCarro;
                    registro["LimiteKM"] = regracontrato.LimiteKMCarro;

                    registro["AnoFab"] = string.Concat("Atual ", (regracontrato.LimiteAnoFabricacao.IdLimiteAnoFabricacao != 1) ? regracontrato.LimiteAnoFabricacao.AnoFabricacao.ToString() : "");
                    if (list.id_limite_ano_fabricacao != 1)
                    {
                        registro["AnoFab"] = string.Concat(registro["AnoFab"].ToString(), (regracontrato.LimiteAnoFabricacao.AnoFabricacao == -1) ? " ano" : " anos");
                    }

                    _gradeRegraContrato.Rows.Add(registro);
                }

                return _gradeRegraContrato;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public DataTable CarregarComboContrato(int _idprestador, int _idpatrocinador)
        {
            try
            {
                _comboContrato = new DataTable();

                EstruturaComboContrato();

                var consulta = (from regracontrato in _context.tab_frota_regra_contrato
                                where regracontrato.tab_contrato.tab_organizacao_relacao_patrocinador.tab_organizacao1.Id_organizacao == _idprestador
                                && regracontrato.tab_contrato.tab_organizacao_relacao_patrocinador.tab_organizacao.Id_organizacao == _idpatrocinador
                                select new
                                {
                                    regracontrato.tab_contrato.Id_contrato
                                }).Distinct();

                var listConsulta = consulta.ToList();

                DataRow registro;
                foreach (var list in listConsulta)
                {
                    FrotaRegraContrato regracontrato = new FrotaRegraContrato();
                    regracontrato.Contrato = new Contrato(list.Id_contrato);

                    registro = _comboContrato.NewRow();
                    registro["IdContrato"] = regracontrato.Contrato.IdContrato;
                    registro["Descricao"] = regracontrato.Contrato.Descricao;

                    _comboContrato.Rows.Add(registro);
                }

                return _comboContrato;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public DataTable CarregarComboLocalidade(int _idprestador, int _idpatrocinador)
        {
            try
            {
                _comboLocalidade = new DataTable();

                EstruturaComboLocalidade();

                var consulta = (from regracontrato in _context.tab_frota_regra_contrato
                                where regracontrato.tab_contrato.tab_organizacao_relacao_patrocinador.tab_organizacao1.Id_organizacao == _idprestador
                                && regracontrato.tab_contrato.tab_organizacao_relacao_patrocinador.tab_organizacao.Id_organizacao == _idpatrocinador
                                select new
                                {
                                    regracontrato.tab_cidade.id_cidade
                                }).Distinct();

                var listConsulta = consulta.ToList();

                DataRow registro;
                foreach (var list in listConsulta)
                {
                    FrotaRegraContrato regracontrato = new FrotaRegraContrato();
                    regracontrato.Localidade = new Cidade(list.id_cidade);

                    registro = _comboLocalidade.NewRow();
                    registro["IdCidade"] = regracontrato.Localidade.IdCidade;
                    registro["NomeCidade"] = regracontrato.Localidade.NomeCidade;

                    _comboLocalidade.Rows.Add(registro);
                }

                return _comboLocalidade;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<Cidade> CarregarLocalidadesOrganizacao(int _organizacao)
        {
            try
            {
                List<Cidade> listCidade = new List<Cidade>();

                var consultaMatriz = (from organizacao in _context.tab_organizacao
                                      join organizacaoend in _context.tab_organizacao_endereco on organizacao.Id_organizacao equals organizacaoend.tab_organizacao.Id_organizacao
                                      join cidade in _context.tab_cidade on organizacaoend.tab_cidade.id_cidade equals cidade.id_cidade
                                      where organizacao.Id_organizacao == _organizacao
                                      select new
                                      {
                                          cidade.id_cidade,
                                          cidade.cidade
                                      });

                var listConsultaMatriz = consultaMatriz.ToList();

                foreach (var list in listConsultaMatriz)
                {
                    Cidade cidade = new Cidade();
                    cidade.IdCidade = list.id_cidade;
                    cidade.NomeCidade = list.cidade;

                    listCidade.Add(cidade);
                }

                var consultaFiliais = (from organizacao in _context.tab_organizacao
                                       join organrelacao in _context.tab_organizacao_relacao_matriz on organizacao.Id_organizacao equals organrelacao.tab_organizacao1.Id_organizacao
                                       join organizacaoend in _context.tab_organizacao_endereco on organizacao.Id_organizacao equals organizacaoend.tab_organizacao.Id_organizacao
                                       join cidade in _context.tab_cidade on organizacaoend.tab_cidade.id_cidade equals cidade.id_cidade
                                       where organrelacao.tab_organizacao.Id_organizacao == _organizacao
                                       select new
                                       {
                                           cidade.id_cidade,
                                           cidade.cidade
                                       });

                var listConsultaFiliais = consultaFiliais.ToList();

                foreach (var list in listConsultaFiliais)
                {
                    Cidade cidade = new Cidade();
                    cidade.IdCidade = list.id_cidade;
                    cidade.NomeCidade = list.cidade;

                    listCidade.Add(cidade);
                }

                return listCidade;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Métodos de Persistência
        public void Salvar()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    if (VerificaCadastro())
                    {
                        if (this._idFrotaRegraContrato == 0)
                        {
                            tab_frota_regra_contrato tabRegraContrato = new tab_frota_regra_contrato();
                            tabRegraContrato.tab_contratoReference.EntityKey = new EntityKey("GENTEEntities.tab_contrato", "Id_contrato", this._contrato.IdContrato);
                            tabRegraContrato.tab_cidadeReference.EntityKey = new EntityKey("GENTEEntities.tab_cidade", "id_cidade", this._localidade.IdCidade);
                            tabRegraContrato.limite_km_por_carro = this._limiteKMCarro;
                            tabRegraContrato.tab_frota_limite_ano_fabricacaoReference.EntityKey = new EntityKey("GENTEEntities.tab_frota_limite_ano_fabricacao", "id_limite_ano_fabricacao", this._limiteAnoFabricacao.IdLimiteAnoFabricacao);
                            tabRegraContrato.qnt_minima_carro = this._qntMinimaCarro;

                            _context.AddTotab_frota_regra_contrato(tabRegraContrato);
                            _context.SaveChanges();

                            this._idFrotaRegraContrato = RetornaIdRegraContrato();

                            SalvarVeiculosFrota();
                        }
                        else
                        {
                            tab_frota_regra_contrato tabRegraContrato = (from regracontrato in _context.tab_frota_regra_contrato
                                                                         where regracontrato.id_frota_regra_contrato == this._idFrotaRegraContrato
                                                                         select regracontrato).First();

                            tabRegraContrato.tab_contratoReference.EntityKey = new EntityKey("GENTEEntities.tab_contrato", "Id_contrato", this._contrato.IdContrato);
                            tabRegraContrato.tab_cidadeReference.EntityKey = new EntityKey("GENTEEntities.tab_cidade", "id_cidade", this._localidade.IdCidade);
                            tabRegraContrato.limite_km_por_carro = this._limiteKMCarro;
                            tabRegraContrato.tab_frota_limite_ano_fabricacaoReference.EntityKey = new EntityKey("GENTEEntities.tab_frota_limite_ano_fabricacao", "id_limite_ano_fabricacao", this._limiteAnoFabricacao.IdLimiteAnoFabricacao);
                            tabRegraContrato.qnt_minima_carro = this._qntMinimaCarro;

                            _context.SaveChanges();

                            ExcluirVeiculosFrota();
                            SalvarVeiculosFrota();
                        }
                    }

                    scope.Complete();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }

        public void Excluir()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    ExcluirVeiculosFrota();

                    var consulta = (from regracontrato in _context.tab_frota_regra_contrato
                                    where regracontrato.id_frota_regra_contrato == this._idFrotaRegraContrato
                                    select regracontrato);

                    var listConsulta = consulta.ToList();

                    foreach (var list in listConsulta)
                    {
                        _context.DeleteObject(list);
                        _context.SaveChanges();
                    }

                    scope.Complete();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
        #endregion

        #endregion
    }
}
